Atrakinkite būsenos mašinų galią „React“ su pasirinktiniais kabliukais. Mokykitės abstrahuoti sudėtingą logiką, pagerinti kodą ir kurti tvirtas programas.
React Custom Hook State Machine: Valdykite sudėtingą būsenos logikos abstrakciją
„React“ programoms tampant sudėtingesnėms, būsenos valdymas gali tapti dideliu iššūkiu. Tradiciniai metodai, naudojantys `useState` ir `useEffect`, greitai gali sukelti supainiotą logiką ir sunkiai prižiūrimą kodą, ypač susiduriant su sudėtingais būsenos perėjimais ir šalutiniais efektais. Štai čia pasitelkiamos būsenos mašinos, o ypač jas įgyvendinantys „React“ pasirinktiniai kabliukai. Šis straipsnis supažindins jus su būsenos mašinų koncepcija, parodys, kaip jas įgyvendinti kaip „React“ pasirinktinius kabliukus, ir pavaizduos privalumus, kuriuos jos suteikia kuriant mastelį turinčias ir prižiūrimas programas pasaulinei auditorijai.
Kas yra Būsenos Mašina?
Būsenos mašina (arba baigtinė būsenos mašina, FSM) yra matematinis skaičiavimo modelis, apibūdinantis sistemos elgesį apibrėžiant baigtinį būsenų skaičių ir perėjimus tarp tų būsenų. Pagalvokite apie tai kaip apie schemą, bet su griežtesnėmis taisyklėmis ir formalesniu apibrėžimu. Pagrindinės sąvokos apima:
- Būsenos: Atspindi skirtingas sistemos sąlygas ar fazes.
- Perėjimai: Apibrėžia, kaip sistema pereina iš vienos būsenos į kitą, remdamasi konkrečiais įvykiais ar sąlygomis.
- Įvykiai: Paleidikliai, sukeliantys būsenos perėjimus.
- Pradinė Būsena: Būsena, kurioje sistema pradeda veikti.
Būsenos mašinos puikiai tinka modeliuoti sistemas su aiškiai apibrėžtomis būsenomis ir skaidriais perėjimais. Pavyzdžių gausu realaus pasaulio scenarijuose:
- Šviesoforai: Ciklu eina per būsenas, tokias kaip Raudona, Geltona, Žalia, su perėjimais, kuriuos paleidžia laikmačiai. Tai yra globaliai atpažįstamas pavyzdys.
- Užsakymų Apdorojimas: El. prekybos užsakymas gali pereiti per būsenas, tokias kaip „Laukiama“, „Apkora“, „Išsiųsta“ ir „Pristatyta“. Tai taikoma universaliai internetinei mažmeninei prekybai.
- Autentifikavimo Eiga: Vartotojo autentifikavimo procesas gali apimti tokias būsenas kaip „Neįsijungęs“, „Jungiamasi“, „Prisijungęs“ ir „Klaida“. Saugos protokolai paprastai yra nuoseklūs visose šalyse.
Kodėl Naudoti Būsenos Mašinas „React“?
Integruojant būsenos mašinas į jūsų „React“ komponentus, suteikiama keletas patrauklių privalumų:
- Pagerintas Kodo Organizavimas: Būsenos mašinos įpareigoja struktūruotą požiūrį į būsenos valdymą, todėl jūsų kodas tampa labiau nuspėjamas ir lengviau suprantamas. Daugiau jokio makaronų kodo!
- Sumažintas Sudėtingumas: Aiškiai apibrėždami būsenas ir perėjimus, galite supaprastinti sudėtingą logiką ir išvengti netyžinių šalutinių efektų.
- Pagerintas Testuojamumas: Būsenos mašinos yra savaime testuojamos. Galite lengvai patikrinti, ar jūsų sistema veikia tinkamai, testuodami kiekvieną būseną ir perėjimą.
- Padidintas Prižiūrimumas: Deklaratyvus būsenos mašinų pobūdis leidžia lengviau keisti ir plėsti kodą, kai jūsų programa tobulėja.
- Geresnės Vizualizacijos: Yra įrankiai, galintys vizualizuoti būsenos mašinas, suteikdami aiškų sistemos elgesio apžvalgą, padedantį bendradarbiauti ir suprasti tarp įvairių įgūdžių turinčių komandų.
Įgyvendinimas Būsenos Mašinos Kaip „React“ Pasirinktinio Kabliuko
Iliustruosime, kaip įgyvendinti būsenos mašiną naudojant „React“ pasirinktinį kabliuką. Sukursime paprastą mygtuko pavyzdį, kuris gali būti trijų būsenų: `idle`, `loading` ir `success`. Mygtukas prasideda `idle` būsenoje. Paspaudus, jis pereina į `loading` būseną, imituoja įkėlimo procesą (naudojant `setTimeout`), o tada pereina į `success` būseną.
1. Apibrėžkite Būsenos Mašiną
Pirmiausia apibrėžime mūsų mygtuko būsenos mašinos būsenas ir perėjimus:
const buttonStateMachineDefinition = {
initial: 'idle',
states: {
idle: {
on: {
CLICK: 'loading',
},
},
loading: {
after: {
2000: 'success', // Po 2 sekundžių pereiti į success
},
},
success: {},
},
};
Ši konfigūracija naudoja bibliotekai nepriklausomą (nors ir įkvėptą XState) požiūrį į būsenos mašinos apibrėžimą. Logiką, kaip interpretuoti šį apibrėžimą, įgyvendinsime patys pasirinktiniame kabliuke. `initial` ypatybė nustato pradinę būseną į `idle`. `states` ypatybė apibrėžia galimas būsenas (`idle`, `loading` ir `success`) bei jų perėjimus. `idle` būsenoje yra `on` ypatybė, apibrėžianti perėjimą į `loading` būseną, kai įvyksta `CLICK` įvykis. `loading` būsenoje naudojama `after` ypatybė, kad automatiškai pereitų į `success` būseną po 2000 milisekundžių (2 sekundžių). `success` būsenoje šiuo atveju yra baigtinė būsena.
2. Sukurkite Pasirinktinį Kabliuką
Dabar sukursime pasirinktinį kabliuką, įgyvendinantį būsenos mašinos logiką:
import { useState, useEffect } from 'react';
const useStateMachine = (stateMachineDefinition) => {
const [currentState, setCurrentState] = useState(stateMachineDefinition.initial);
const [context, setContext] = useState({});
const transition = (event) => {
const stateDefinition = stateMachineDefinition.states[currentState];
if (stateDefinition && stateDefinition.on && stateDefinition.on[event]) {
setCurrentState(stateDefinition.on[event]);
}
};
useEffect(() => {
const stateDefinition = stateMachineDefinition.states[currentState];
if (stateDefinition && stateDefinition.after) {
const timeoutKeys = Object.keys(stateDefinition.after);
timeoutKeys.forEach(timeoutKey => {
const timeout = parseInt(timeoutKey, 10);
const nextState = stateDefinition.after[timeoutKey];
const timer = setTimeout(() => {
setCurrentState(nextState);
clearTimeout(timer);
}, timeout);
return () => clearTimeout(timer); // Valymas išjungus arba pakeitus būseną
});
}
}, [currentState, stateMachineDefinition.states]);
return {
currentState,
context,
transition,
};
};
export default useStateMachine;
Šis `useStateMachine` kabliukas priima būsenos mašinos apibrėžimą kaip argumentą. Jis naudoja `useState` būsenai ir kontekstui valdyti (kontekstą paaiškinsime vėliau). `transition` funkcija priima įvykį kaip argumentą ir atnaujina dabartinę būseną, remdamasi apibrėžtais būsenos mašinos apibrėžimo perėjimais. `useEffect` kabliukas tvarko `after` ypatybę, nustatydamas laikmačius, kad automatiškai pereitų į kitą būseną po nurodyto laiko. Kabliukas grąžina dabartinę būseną, kontekstą ir `transition` funkciją.
3. Naudokite Pasirinktinį Kabliuką Komponentėje
Galiausiai, naudokime pasirinktinį kabliuką „React“ komponente:
import React from 'react';
import useStateMachine from './useStateMachine';
const buttonStateMachineDefinition = {
initial: 'idle',
states: {
idle: {
on: {
CLICK: 'loading',
},
},
loading: {
after: {
2000: 'success', // Po 2 sekundžių pereiti į success
},
},
success: {},
},
};
const MyButton = () => {
const { currentState, transition } = useStateMachine(buttonStateMachineDefinition);
const handleClick = () => {
if (currentState === 'idle') {
transition('CLICK');
}
};
let buttonText = 'Click Me';
if (currentState === 'loading') {
buttonText = 'Loading...';
} else if (currentState === 'success') {
buttonText = 'Success!';
}
return (
);
};
export default MyButton;
Ši komponentė naudoja `useStateMachine` kabliuką mygtuko būsenai valdyti. `handleClick` funkcija išsiunčia `CLICK` įvykį, kai mygtukas yra paspaudžiamas (ir tik jei jis yra `idle` būsenoje). Komponentė rodo skirtingą tekstą, priklausomai nuo dabartinės būsenos. Mygtukas yra išjungtas įkėlimo metu, kad būtų išvengta daugkartinių paspaudimų.
Konteksto Valdymas Būsenos Mašinose
Daugelyje realaus pasaulio scenarijų būsenos mašinos turi valdyti duomenis, kurie išlieka per būsenos perėjimus. Šie duomenys vadinami kontekstu. Kontekstas leidžia saugoti ir atnaujinti susijusią informaciją, kai būsenos mašina progresuoja.
Panaudosime mūsų mygtuko pavyzdį, kad įtrauktume skaitiklį, kuris padidėja kiekvieną kartą, kai mygtukas sėkmingai įkeliama. Atnaujinsime būsenos mašinos apibrėžimą ir pasirinktinį kabliuką, kad galėtume valdyti kontekstą.
1. Atnaujinkite Būsenos Mašinos Apibrėžimą
const buttonStateMachineDefinition = {
initial: 'idle',
context: {
count: 0,
},
states: {
idle: {
on: {
CLICK: 'loading',
},
},
loading: {
after: {
2000: 'success',
},
},
success: {
entry: (context) => {
return { ...context, count: context.count + 1 };
},
},
},
};
Pridėjome `context` ypatybę būsenos mašinos apibrėžime su pradiniu `count` reikšme 0. Taip pat pridėjome `entry` veiksmą `success` būsenai. `entry` veiksmas vykdomas, kai būsenos mašina patenka į `success` būseną. Jis priima dabartinį kontekstą kaip argumentą ir grąžina naują kontekstą su padidintu `count`. `entry` čia parodo pavyzdį, kaip modifikuoti kontekstą. Kadangi JavaScript objektai perduodami pagal nuorodą, svarbu grąžinti *naują* objektą, o ne modifikuoti originalų.
2. Atnaujinkite Pasirinktinį Kabliuką
import { useState, useEffect } from 'react';
const useStateMachine = (stateMachineDefinition) => {
const [currentState, setCurrentState] = useState(stateMachineDefinition.initial);
const [context, setContext] = useState(stateMachineDefinition.context || {});
const transition = (event) => {
const stateDefinition = stateMachineDefinition.states[currentState];
if (stateDefinition && stateDefinition.on && stateDefinition.on[event]) {
setCurrentState(stateDefinition.on[event]);
}
};
useEffect(() => {
const stateDefinition = stateMachineDefinition.states[currentState];
if(stateDefinition && stateDefinition.entry){
const newContext = stateDefinition.entry(context);
setContext(newContext);
}
if (stateDefinition && stateDefinition.after) {
const timeoutKeys = Object.keys(stateDefinition.after);
timeoutKeys.forEach(timeoutKey => {
const timeout = parseInt(timeoutKey, 10);
const nextState = stateDefinition.after[timeoutKey];
const timer = setTimeout(() => {
setCurrentState(nextState);
clearTimeout(timer);
}, timeout);
return () => clearTimeout(timer); // Valymas išjungus arba pakeitus būseną
});
}
}, [currentState, stateMachineDefinition.states, context]);
return {
currentState,
context,
transition,
};
};
export default useStateMachine;
Atnaujinome `useStateMachine` kabliuką, kad inicializuotume `context` būseną su `stateMachineDefinition.context` arba tuščiu objektu, jei kontekstas nepateiktas. Taip pat pridėjome `useEffect`, kad tvarkytume `entry` veiksmą. Kai dabartinė būsena turi `entry` veiksmą, mes jį vykdome ir atnaujiname kontekstą su grąžinta reikšme.
3. Naudokite Atnaujintą Kabliuką Komponentėje
import React from 'react';
import useStateMachine from './useStateMachine';
const buttonStateMachineDefinition = {
initial: 'idle',
context: {
count: 0,
},
states: {
idle: {
on: {
CLICK: 'loading',
},
},
loading: {
after: {
2000: 'success',
},
},
success: {
entry: (context) => {
return { ...context, count: context.count + 1 };
},
},
},
};
const MyButton = () => {
const { currentState, context, transition } = useStateMachine(buttonStateMachineDefinition);
const handleClick = () => {
if (currentState === 'idle') {
transition('CLICK');
}
};
let buttonText = 'Click Me';
if (currentState === 'loading') {
buttonText = 'Loading...';
} else if (currentState === 'success') {
buttonText = 'Success!';
}
return (
Count: {context.count}
);
};
export default MyButton;
Dabar komponentėje pasiekiame `context.count` ir jį rodome. Kiekvieną kartą, kai mygtukas sėkmingai įkeliama, skaitiklis padidės.
Pažangios Būsenos Mašinų Koncepcijos
Nors mūsų pavyzdys yra gana paprastas, būsenos mašinos gali tvarkyti daug sudėtingesnius scenarijus. Štai keletas pažangių koncepcijų, kurias verta apsvarstyti:
- Apsaugos (Guards): Sąlygos, kurios turi būti įvykdytos, kad įvyktų perėjimas. Pavyzdžiui, perėjimas gali būti leidžiamas tik tuo atveju, jei vartotojas yra autentifikuotas arba jei tam tikra duomenų reikšmė viršija nustatytą ribą.
- Veiksmai (Actions): Šalutiniai efektai, kurie vykdomi įeinant arba išeinant iš būsenos. Tai gali būti API iškvietimai, DOM atnaujinimai arba įvykių siuntimas į kitas komponentes.
- Lygiagrečios Būsenos (Parallel States): Leidžia modeliuoti sistemas su keliais lygiagrečiais veiksmais. Pavyzdžiui, vaizdo grotuvas gali turėti vieną būsenos mašiną atkūrimo valdymui (paleisti, pristabdyti, sustabdyti) ir kitą vaizdo kokybei valdyti (žema, vidutinė, aukšta).
- Hierarchinės Būsenos (Hierarchical States): Leidžia įterpti būsenas į kitas būsenas, sukuriant būsenų hierarchiją. Tai gali būti naudinga modeliuojant sudėtingas sistemas su daug susijusių būsenų.
Alternatyvios Bibliotekos: XState ir Kitos
Nors mūsų pasirinktinis kabliukas suteikia pagrindinį būsenos mašinos įgyvendinimą, kelios puikios bibliotekos gali supaprastinti procesą ir pasiūlyti pažangesnių funkcijų.
XState
XState yra populiari JavaScript biblioteka, skirta būsenos mašinoms ir būsenos diagramoms kurti, interpretuoti ir vykdyti. Ji suteikia galingą ir lanksčią API sudėtingoms būsenos mašinoms apibrėžti, įskaitant apsaugų, veiksmų, lygiagrečių būsenų ir hierarchinių būsenų palaikymą. XState taip pat siūlo puikius įrankius būsenos mašinoms vizualizuoti ir derinti.
Kitos Bibliotekos
Kitos galimybės apima:
- Robot: Lengva būsenos valdymo biblioteka, orientuota į paprastumą ir našumą.
- react-automata: Biblioteka, specialiai sukurta integruoti būsenos mašinas į „React“ komponentus.
Bibliotekos pasirinkimas priklauso nuo jūsų projekto specifinių poreikių. XState yra geras pasirinkimas sudėtingoms būsenos mašinoms, o Robot ir react-automata tinka paprastesniems scenarijams.
Geriausios Praktikos Naudojant Būsenos Mašinas
Kad galėtumėte efektyviai išnaudoti būsenos mašinas „React“ programose, apsvarstykite šias geriausias praktikas:
- Pradėkite nuo Mažo: Pradėkite nuo paprastų būsenos mašinų ir palaipsniui didinkite sudėtingumą, kai reikia.
- Vizualizuokite Savo Būsenos Mašiną: Naudokite vizualizavimo įrankius, kad aiškiai suprastumėte savo būsenos mašinos elgesį.
- Rašykite Išsamius Testus: Kruopščiai testuokite kiekvieną būseną ir perėjimą, kad užtikrintumėte tinkamą sistemos elgesį.
- Dokumentuokite Savo Būsenos Mašiną: Aiškiai dokumentuokite būsenos mašinos būsenas, perėjimus, apsaugas ir veiksmus.
- Apsvarstykite Tarptautinimą (i18n): Jei jūsų programa skirta pasaulinei auditorijai, įsitikinkite, kad jūsų būsenos mašinos logika ir vartotojo sąsaja yra tinkamai tarptautintos. Pavyzdžiui, naudokite atskiras būsenos mašinas arba kontekstą skirtingoms datos formatams ar valiutos simboliams tvarkyti, priklausomai nuo vartotojo lokacijos.
- Prieinamumas (a11y): Įsitikinkite, kad jūsų būsenos perėjimai ir UI atnaujinimai yra prieinami neįgaliems vartotojams. Naudokite ARIA atributus ir semantinį HTML, kad suteiktumėte tinkamą kontekstą ir grįžtamąjį ryšį pagalbinei technologijai.
Išvada
„React“ pasirinktiniai kabliukai kartu su būsenos mašinomis suteikia galingą ir efektyvų būdą valdyti sudėtingą būsenos logiką „React“ programose. Abstrahuojant būsenos perėjimus ir šalutinius efektus į gerai apibrėžtą modelį, galite pagerinti kodo organizavimą, sumažinti sudėtingumą, padidinti testuojamumą ir prižiūrimumą. Nesvarbu, ar įgyvendinsite savo pasirinktinį kabliuką, ar pasinaudosite tokia biblioteka kaip XState, būsenos mašinų įtraukimas į jūsų „React“ darbo eigą gali žymiai pagerinti jūsų programų kokybę ir mastelį visame pasaulyje.